#ifndef MY_VECTOR_H
#define MY_VECTOR_H

#include <iostream>
namespace math {

    template<typename T>
    class Vector3;

    template<typename T>
    class Vector4;

    template<typename T>
    class Vector2
    {
    public:
        T m_x,m_y;

        Vector2(){ m_x = m_y = 0;
                 }
        Vector2(T x, T y):m_x(x),m_y(y){}
        Vector2(const Vector2<T>& v):m_x(v.m_x),m_y(v.m_y){}
        Vector2(const Vector3<T>& v):m_x(v.m_x),m_y(v.m_y){}
        Vector2(const Vector4<T>& v):m_x(v.m_x),m_y(v.m_y){}

        /*
        * 取得向量某个元素
        * int a = v[1]
        */

        T operator[](int index) const
        {
            if(0 == index)
            {
                return m_x;
            }
            else if (1 == index)
            {
                return m_y;
            }
            else
            {
                return m_x;
            }
        }

       //等号运算符重载
       Vector2<T> operator=(const Vector3<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           return *this;
       }

       Vector2<T> operator=(const Vector4<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           return *this;
       }

       /*
       * 加法
       * v = v1+v2
       */
       Vector2<T> operator+(const Vector2<T>& v)
       {

           return Vector2(m_x + v.m_x, m_y + v.m_y);
       }

       /*
       * 加法并赋值
       * v += v2
       */
       Vector2<T> operator+=(const Vector2<T>& v)
       {
           m_x += v.m_x;
           m_y += v.m_y;
           return *this;
       }

       /*
       * 乘法
       * v = v1 * s
       */
       Vector2<T> operator*(T s) const
       {
          return Vector2(m_x * s, m_y * s);
       }

       /*
       * 乘法并赋值
       * v *= s
       */
       Vector2<T> operator*=(T s)
       {
           m_x *= s;
           m_y *= s;
           return *this;
       }


       /*
       * 除法
       * v = v1 / f
       */
       Vector2<T> operator/(T f) const
       {
           if(0 == f)
           {
               return Vector2();
           }

           return Vector2(m_x / f, m_y / f);
       }

       /*
       * 除法并赋值
       * v /= f
       */
       Vector2<T> operator/=(T f)
       {
           if(0 == f)
           {
               return Vector2();
           }

           m_x /= f;
           m_y /= f;
           return *this;
       }

       /*
       * 负号操作
       * v = -v1
       */
       Vector2<T> operator-()
       {
           return Vector2(-m_x, -m_y);
       }
    };

    template<typename T>
    class Vector3
    {
    public:
        T m_x,m_y,m_z;

        Vector3(){ m_x = m_y = m_z = 0; }
        Vector3(T x, T y, T z):m_x(x),m_y(y),m_z(z){}
        Vector3(const Vector2<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(0){}
        Vector3(const Vector3<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(v.m_z){}
        Vector3(const Vector4<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(v.m_z){}

        /*
        * 取得向量某个元素
        * int a = v[1]
        */

        T operator[](int index) const
        {
            if(0 == index)
            {
                return m_x;
            }
            else if (1 == index)
            {
                return m_y;
            }
            else if (2 == index)
            {
                return m_z;
            }
            else
            {
                return m_x;
            }
        }

       //等号运算符重载
       Vector3<T> operator=(const Vector2<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           m_z = 0;
           return *this;
       }

       Vector3<T> operator=(const Vector4<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           m_z = v.m_z;
           return *this;
       }

       /*
       * 加法
       * v = v1+v2
       */
       Vector3<T> operator+(const Vector3<T>& v)
       {

           return Vector3(m_x + v.m_x, m_y + v.m_y, m_z + v.m_z);
       }

       /*
       * 加法并赋值
       * v += v2
       */
       Vector3<T> operator+=(const Vector3<T>& v)
       {
           m_x += v.m_x;
           m_y += v.m_y;
           m_z += v.m_z;
           return *this;
       }

       /*
       * 乘法
       * v = v1 * s
       */
       Vector3<T> operator*(T s) const
       {
          return Vector3(m_x * s, m_y * s, m_z * s);
       }

       /*
       * 乘法并赋值
       * v *= s
       */
       Vector3<T> operator*=(T s)
       {
           m_x *= s;
           m_y *= s;
           m_z *= s;
           return *this;
       }


       /*
       * 除法
       * v = v1 / f
       */
       Vector3<T> operator/(T f) const
       {
           if(0 == f)
           {
               return Vector3();
           }

           return Vector3(m_x / f, m_y / f, m_z / f);
       }

       /*
       * 除法并赋值
       * v /= f
       */
       Vector3<T> operator/=(T f)
       {
           if(0 == f)
           {
               return Vector3();
           }

           m_x /= f;
           m_y /= f;
           m_z /= f;
           return *this;
       }

       /*
       * 负号操作
       * v = -v1
       */
       Vector3<T> operator-()
       {
           return Vector3(-m_x, -m_y, -m_z);
       }

    };

    template<typename T>
    class Vector4
    {
    public:
        T m_x,m_y,m_z,m_w;

        Vector4(){ m_x = m_y = m_z = m_w = 0; }
        Vector4(T x, T y, T z, T w):m_x(x),m_y(y),m_z(z),m_w(w){}
        Vector4(const Vector2<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(0),m_w(0){}
        Vector4(const Vector3<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(v.m_z),m_w(0){}
        Vector4(const Vector4<T>& v):m_x(v.m_x),m_y(v.m_y),m_z(v.m_z),m_w(v.m_w){}

        /*
        * 取得向量某个元素
        * int a = v[1]
        */
        T operator[](int index) const
        {
            if(0 == index)
            {
                return m_x;
            }
            else if (1 == index)
            {
                return m_y;
            }
            else if (2 == index)
            {
                return m_z;
            }
            else if(3 == index)
            {
                return m_w;
            }
            else
            {
                return m_x;
            }
        }

       //等号运算符重载
       Vector4<T> operator=(const Vector2<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           m_z = 0;
           m_w = 0;
           return *this;
       }

       Vector4<T> operator=(const Vector3<T>& v)
       {
           m_x = v.m_x;
           m_y = v.m_y;
           m_z = v.m_z;
           m_w = 0;
           return *this;
       }

       /*
       * 加法
       * v = v1+v2
       */
       Vector4<T> operator+(const Vector4<T>& v)
       {

           return Vector4(m_x + v.m_x, m_y + v.m_y, m_z + v.m_z, m_w + v.m_w);
       }

       /*
       * 加法并赋值
       * v += v2
       */
       Vector4<T> operator+=(const Vector4<T>& v)
       {
           m_x += v.m_x;
           m_y += v.m_y;
           m_z += v.m_z;
           m_w += v.m_w;
           return *this;
       }

       /*
       * 乘法
       * v = v1 * s
       */
       Vector4<T> operator*(T s) const
       {
          return Vector4(m_x * s, m_y * s, m_z * s, m_w * s);
       }

       /*
       * 乘法并赋值
       * v *= s
       */
       Vector4<T> operator*=(T s)
       {
           m_x *= s;
           m_y *= s;
           m_z *= s;
           m_w *= s;
           return *this;
       }


       /*
       * 除法
       * v = v1 / f
       */
       Vector4<T> operator/(T f) const
       {
           if(0 == f)
           {
               return Vector4();
           }

           return Vector4(m_x / f, m_y / f, m_z /f, m_w / f);
       }

       /*
       * 除法并赋值
       * v /= f
       */
       Vector4<T> operator/=(T f)
       {
           if(0 == f)
           {
               return Vector4();
           }

           m_x /= f;
           m_y /= f;
           m_z /= f;
           m_w /= f;
           return *this;
       }

       /*
       * 负号操作
       * v = -v1
       */
       Vector4<T> operator-()
       {
           return Vector4(-m_x, -m_y, -m_z, -m_w);
       }

     };

     using vec2f = Vector2<float>;
     using vec2i = Vector2<int>;
     using vec3f = Vector3<float>;
     using vec3i = Vector3<int>;
     using vec4f = Vector4<float>;
     using vec4i = Vector4<int>;

}

#endif // MY_VECTOR_H
